package vsm.vsm_server.service.impl; // 保持你的包名

import com.fasterxml.jackson.core.type.TypeReference; // 确保导入
import com.fasterxml.jackson.databind.ObjectMapper; // 确保导入
import lombok.extern.slf4j.Slf4j; // 使用 Lombok 的 @Slf4j 注解
import org.springframework.beans.factory.annotation.Autowired; // 确保导入
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate; // 确保导入
import vsm.vsm_server.pojo.Video.VideoScore; // 保持你的 Pojo 路径
import vsm.vsm_server.service.PredictService; // 保持你的 Service 接口路径

import java.io.IOException; // 确保导入
import java.math.BigInteger;
import java.util.*;

@Service
@Slf4j // 使用 Lombok 自动生成 log 字段
public class PredictServiceImpl implements PredictService { // 假设 PredictService 接口存在

    @Value("${python.api.url}") // 确保配置文件中有 python.api.url
    private String pythonApiUrl;

    @Autowired // 注入 RestTemplate Bean
    private RestTemplate restTemplate;

    @Autowired // 注入 ObjectMapper Bean
    private ObjectMapper objectMapper;

    @Override // 假设接口中有此方法
    // --- *** 修改返回类型为 Map<BigInteger, Double> *** ---
    public Map<BigInteger, Double> predictVideoList(List<VideoScore> videoScoreList) {
        // --- *** 初始化为 HashMap *** ---
        Map<BigInteger, Double> resultMap = new HashMap<>();
        if (videoScoreList == null || videoScoreList.isEmpty()) {
            return resultMap; // 返回空 Map
        }

        List<Map<String, Object>> instances = new ArrayList<>();
        Map<String, BigInteger> stringToBigIntVideoIdMap = new HashMap<>();

        for (VideoScore videoScore : videoScoreList) {
            if (videoScore == null || videoScore.getUserId() == null || videoScore.getVideoId() == null || videoScore.getTagId() == null) {
                log.warn("Skipping invalid VideoScore entry with null fields.");
                continue;
            }
            Map<String, Object> instance = new HashMap<>();
            String userIdStr = videoScore.getUserId().toString();
            String videoIdStr = videoScore.getVideoId().toString();
            String tagIdStr = videoScore.getTagId().toString();
            instance.put("userId", userIdStr);
            instance.put("videoId", videoIdStr);
            instance.put("tagId", tagIdStr);
            instances.add(instance);
            stringToBigIntVideoIdMap.put(videoIdStr, videoScore.getVideoId());
        }

        if (instances.isEmpty()) {
            log.warn("No valid instances to send for prediction after filtering.");
            return resultMap; // 返回空 Map
        }

        Map<String, Object> requestBody = new HashMap<>();
        requestBody.put("instances", instances);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestBody, headers);

        ResponseEntity<String> responseEntity;
        try {
            log.debug("Sending {} instances to prediction service at {}", instances.size(), pythonApiUrl);
            responseEntity = restTemplate.postForEntity(pythonApiUrl, requestEntity, String.class);
        } catch (RestClientException e) {
            log.error("Error calling prediction service at {}: {}", pythonApiUrl, e.getMessage(), e);
            return resultMap; // 返回空 Map
        }

        if (responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null) {
            String responseBody = responseEntity.getBody();
            log.debug("Received prediction response: {}", responseBody);
            try {
                Map<String, List<Map<String, Object>>> result = objectMapper.readValue(responseBody,
                        new TypeReference<Map<String, List<Map<String, Object>>>>() {});

                List<Map<String, Object>> predictions = result.get("predictions");

                if (predictions != null) {
                    log.debug("Processing {} predictions.", predictions.size());
                    for (Map<String, Object> prediction : predictions) {
                        Object videoIdObj = prediction.get("videoId");
                        Object scoreObj = prediction.get("score");

                        if (videoIdObj instanceof String && scoreObj instanceof Number) {
                            String videoIdStr = (String) videoIdObj;
                            double score = ((Number) scoreObj).doubleValue();
                            BigInteger originalVideoId = stringToBigIntVideoIdMap.get(videoIdStr);

                            if (originalVideoId != null) {
                                if (score == -1.0) {
                                    log.debug("Received default score (-1.0) for videoId {}, assigning lowest possible score.", originalVideoId);
                                    score = -Double.MAX_VALUE;
                                }
                                // --- *** 直接放入结果 Map *** ---
                                resultMap.put(originalVideoId, score);
                            } else {
                                log.warn("Could not find original BigInteger for received videoId string: {}. This prediction will be skipped.", videoIdStr);
                            }
                        } else {
                            log.warn("Invalid format in prediction item: {}", prediction);
                        }
                    }
                    if (predictions.size() != instances.size()) {
                        log.warn("Mismatch between sent instances ({}) and received predictions ({}). Some predictions might be missing or extra.", instances.size(), predictions.size());
                    }
                } else {
                    log.error("Parsed predictions list is null in response body. JSON structure might be incorrect: {}", responseBody);
                }
            } catch (IOException e) {
                log.error("Error parsing prediction response JSON: {}", responseBody, e);
            } catch (ClassCastException e) {
                log.error("Error casting parts of the parsed JSON structure. Check JSON format and TypeReference. Response: {}", responseBody, e);
            }
        } else {
            log.error("Prediction service returned non-2xx status ({}) or empty body.", responseEntity.getStatusCode());
        }

        // --- *** 修改日志信息和返回变量 *** ---
        log.info("Finished processing predictions, returning score map with size: {}", resultMap.size());
        log.info("{}",resultMap);
        return resultMap; // 返回结果 Map
    }
}